Item6-若不想使用编译器自动生成的函数,就该明确拒绝

拒绝编译器自动提供的机制

通过显式声明一个成员函数,可以防止编译器生成它自己的版本,而且将这个函数声明为私有的,可以防止别人调用它。

一般而言这个做法并不绝对安全,因为member 函数和友元函数还是能够调用你的 private 函数。除非你十分聪明地不定义它们,那么,当有人不小心地调用了它们,在 link-time(链接时)会出现一个连接错误(linkage error)。

“将成员函数声明为 private 而且故意不实现它们”这一伎俩被大多数人接受,因而被用在 C++ iostream 程序库中阻止 copying 行为。

class HomeForSale {
public:
  ...
private:
  ...
  //@ declarations only
  HomeForSale(const HomeForSale&);	//参数名称并非必要,当这个函数不实现了也就没必要写出来了
  HomeForSale& operator=(const HomeForSale&);
};

通常会专门设计一个阻止 copying 动作的 base class 内:

class Uncopyable {
protected:                                  
  Uncopyable() {}                           
  ~Uncopyable() {}                          

private:
 //@but prevent copying
  Uncopyable(const Uncopyable&);             
  Uncopyable& operator=(const Uncopyable&);
};

阻止 HomeForSale 对象被拷贝,唯一需要做的就是继承 Uncopyable:

class HomeForSale: private Uncopyable {      
  ...                                        
};  

这样行得通,因为只要任何人(包括member 函数或 friend 函数)尝试拷贝 HomeForSale 对象,编译器便尝试着生成一个 copy 构造函数和一个 copy assignment 操作符,这些编译器生成的函数会尝试调用基类的对应函数,而这些调用将被拒绝,因为基类的拷贝函数是 private的。

Uncopyable 的实现和使用颇为微妙:

  • 从 Uncopyable 继承不必是 public的
  • Uncopyable 的 析构函数不必是 virtual 的。因为 Uncopyable 不包含数据

总结

  • 为了驳回编译器自动(暗自)提供的机能,将相应的成员函数声明为 private 并且不予实现

  • 使用像 Uncopyable 这样的基类也是一种做法